﻿using System;
using Liphofra.Core;
using Liphofra.Core.EventAggregation;
using Liphofra.Mvvm.Navigation;

namespace Liphofra.Mvvm.ViewModels
{
    /// <summary>
    /// An implementation of a view model factory that is able to create and configure view models.
    /// </summary>
    public sealed class ViewModelFactory : IViewModelFactory
    {
        private readonly IServiceLocator _serviceLocator;

        /// <summary>
        /// Initializes a new instance of the <see cref="ViewModelFactory"/> class.
        /// </summary>
        /// <param name="serviceLocator">The service locator dependency.</param>
        public ViewModelFactory(IServiceLocator serviceLocator)
        {
            _serviceLocator = serviceLocator;
        }

        /// <summary>
        /// Creates and pre-configures a view model of the given type.
        /// </summary>
        /// <param name="type">The type of the view model to create.</param>
        /// <returns>
        /// A newly created, pre-configured view model.
        /// </returns>
        public object CreateViewModel(Type type)
        {
            var result = _serviceLocator.Resolve(type);

            if (result != null)
            {
                ConfigureViewModel(result);
            }

            return result;
        }

        /// <summary>
        /// Creates and pre-configures a view model of the given type.
        /// </summary>
        /// <typeparam name="T">The type of the view model to create.</typeparam>
        /// <returns>
        /// A newly created, pre-configured view model.
        /// </returns>
        public T CreateViewModel<T>() where T : class
        {
            var result = _serviceLocator.Resolve<T>();

            if (result != null)
            {
                ConfigureViewModel(result);
            }

            return result;
        }

        private void ConfigureViewModel(object result)
        {
            var viewModel = result as IViewModel;
            if (viewModel != null)
            {
                viewModel.ServiceLocator = _serviceLocator;
            }

            var navigationViewModel = result as INavigationViewModel;
            if (navigationViewModel != null)
            {
                // pre-configure the navigation service and event aggregator
                navigationViewModel.NavigationService = _serviceLocator.Resolve<INavigationService>();
                navigationViewModel.EventAggregator = _serviceLocator.Resolve<IEventAggregator>();
            }
        }
    }
}